Caracterización de las series de tiempo --------------------------------------- Ruido blanco (White Noise) ~~~~~~~~~~~~~~~~~~~~~~~~~~ Un Ruido Blanco es una serie temporal que no tiene un patrón y por lo cual no se puede predecir el futuro. Para que la serie de tiempo sea Ruido Blanco debe tener: 1. Media constante. 2. Varianza constante. 3. Sin autocorrelaciones en ningún período. El Ruido Blanco es una secuencia de datos aleatorios donde cada valor tiene un período de tiempo asociado y la serie de tiempo se tiene un comportamiento aleatorio y no se puede proyectar el futuro. Autocorrelación ~~~~~~~~~~~~~~~ Mide la correlación de la serie con versiones anteriores de la misma. .. math:: \rho=corr(x_t,x_{t-1}) La falta de autoccorrelación significa que no hay una relación entre valores pasados y valores presentes. .. code:: ipython3 import pandas as pd import numpy as np .. code:: ipython3 datos = pd.read_csv('Precio.csv', sep=';', decimal=',') .. code:: ipython3 len(datos) .. parsed-literal:: 5817 .. code:: ipython3 datos.head() .. raw:: html
Fecha Precio
0 1/03/2003 72.412500
1 2/03/2003 72.837083
2 3/03/2003 70.103750
3 4/03/2003 70.770417
4 5/03/2003 69.153750
.. code:: ipython3 datos.tail() .. raw:: html
Fecha Precio
5812 27/01/2019 240.19
5813 28/01/2019 306.09
5814 29/01/2019 296.29
5815 30/01/2019 298.31
5816 31/01/2019 309.06
Convertir la columna Fecha de los datos cargados como fechas. .. code:: ipython3 datos.Fecha = pd.to_datetime(datos.Fecha, dayfirst = True) .. code:: ipython3 datos.head() .. raw:: html
Fecha Precio
0 2003-03-01 72.412500
1 2003-03-02 72.837083
2 2003-03-03 70.103750
3 2003-03-04 70.770417
4 2003-03-05 69.153750
Convertir las fechas como el index. .. code:: ipython3 datos.set_index('Fecha', inplace=True) .. code:: ipython3 datos.head() .. raw:: html
Precio
Fecha
2003-03-01 72.412500
2003-03-02 72.837083
2003-03-03 70.103750
2003-03-04 70.770417
2003-03-05 69.153750
Gráfica de la serie de tiempo cargada ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .. code:: ipython3 import matplotlib.pyplot as plt .. code:: ipython3 datos.plot() plt.show() .. image:: output_22_0.png Como las fechas se convirtieron a index, salen en el eje X del gráfico. Ejemplo de Ruido Blanco ~~~~~~~~~~~~~~~~~~~~~~~ Se creará una serie de tiempo Ruido Blanco a partir de la media y la desviación estándar de los datos cargados .. code:: ipython3 wn = np.random.normal(loc = datos.mean(), scale = datos.std(), size = len(datos)) .. code:: ipython3 datos['wn'] = wn #Para agregar los valores de wn en una columna. .. code:: ipython3 datos.head() .. raw:: html
Precio wn
Fecha
2003-03-01 72.412500 68.762652
2003-03-02 72.837083 -12.488899
2003-03-03 70.103750 150.336584
2003-03-04 70.770417 15.468834
2003-03-05 69.153750 8.528356
.. code:: ipython3 datos.describe() .. raw:: html
Precio wn
count 5817.000000 5817.000000
mean 139.017727 139.923242
std 144.002145 142.741753
min 35.940000 -306.202509
25% 70.983333 43.546751
50% 97.480000 142.477725
75% 155.160000 236.312871
max 1952.180000 668.576254
Gráfico de la serie de tiempo Ruido Blanco ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .. code:: ipython3 datos.wn.plot(figsize = (20,5)) plt.title("White Noise Time-Series", size= 24) plt.show() .. image:: output_31_0.png Caminata Aleatoria (Random Walk) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ En la Caminata Aleatoria los valores tienen a persistir en el tiempo y las diferencias entre períodos son Ruido Blanco. .. math:: P_t=P_{t-1}+\epsilon_t :math:`\epsilon_t:` es un residuo aleatorio Ruido Blanco. La mejor estimación de :math:`P_t` es :math:`P_{t-1}`. Los patrones pasados persistirán en el futuro. Así, la mejor estimación del precio de mañana será el precio de hoy. .. math:: \epsilon_t\sim WN(\mu,\sigma^2) Ejemplo de Caminata Aleatoria ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .. code:: ipython3 rw = pd.read_csv('RandWalk.csv', sep=',', decimal='.') .. code:: ipython3 rw.head() .. raw:: html
date price
0 07/01/1994 1122.139662
1 08/01/1994 1135.238562
2 09/01/1994 1109.897831
3 10/01/1994 1080.347860
4 11/01/1994 1082.095245
.. code:: ipython3 rw.date = pd.to_datetime(rw.date, dayfirst = True) rw.set_index('date', inplace=True) .. code:: ipython3 rw.head() .. raw:: html
price
date
1994-01-07 1122.139662
1994-01-08 1135.238562
1994-01-09 1109.897831
1994-01-10 1080.347860
1994-01-11 1082.095245
.. code:: ipython3 rw.plot(figsize = (20,5)) plt.title("Random Walk", size= 24) plt.show() .. image:: output_43_0.png Generación de Caminata Aleatoria ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .. code:: ipython3 # Generamos 500 pasos aleatorios para la caminara, con media 0 y desviación estándar 1 steps = np.random.normal(loc=0, scale=1, size=500) .. code:: ipython3 # Ponemos el primer elemento a 0 para que el precio inicial sea el que pongamos nosotros steps[0]=0 .. code:: ipython3 # Simulando los precios P con un precio inicial de 100 P = 100 + np.cumsum(steps) .. code:: ipython3 plt.plot(P) plt.title("Random Walk Simulada") plt.show() .. image:: output_48_0.png Esta gráfica se generará aleatoriamente, es decir, que siempre será una diferente cada vez que se corre el código. Estacionariedad (Stationarity) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Una serie de tiempo es estacionaria cuanda la media y la varianza son constantes en el tiempo y no tiene tendencia. Los valores de la serie de tiempo oscilan alrededor de la media constante y la variabilidad con respecto a esa media también permanece constante en el tiempo. Por el contrario, las series no estacionarias tienen tendencia o la variabilidad cambia en el tiempo. Los cambios en la media determinan una tendecia y los valores no oscilarán alrededor de la media. :math:`\mu:` Media constante. :math:`\sigma^2:` Varianza constante. Esto implica, que si la serie de tiempo es estacionaria: .. math:: cov(S_1)=cov(S_2) Esto también se conoce como estacionariedad en forma débil. Entonces, la serie de tiempo tiene estacionariedad en forma débil o estacionariedad en covarianzas. Una serie de tiempo es estacionaria en covarianza si cumple con los siguientes tres supuestos: 1. :math:`\mu:` Media constante. 2. :math:`\sigma^2:` Varianza constante. 3. Datos con covarianza constante entre períodos que estén a una distancia idéntica al otro dato (:math:`k`): .. math:: cov(x_n,x_{n+k}) = cov(x_m,x_{m+k}) El Ruido Blanco es una serie de tiempo estacionaria en covarianza o débilmente estacionaria Adicionalmente, el Ruido Blanco no presenta autocorrelaciones. Por tanto, la correlación entre dos puntos en el tiempo (:math:`x_n,x_{x+k}`) es igual a cero. En consecuencia, si :math:`corr(x_n,x_{x+k})=0`, entonces, :math:`cov(x_n,x_{n+k})=0`. .. math:: cov(x_n,x_{n+k})=corr(x_n,x_{x+k})\sigma_n\sigma_{n+k} Estacionariedad Estricta ~~~~~~~~~~~~~~~~~~~~~~~~ Esto significa que las muestras aleatorias de la serie de tiempo tienen la misma distribución, es decir, distribuciones idénticas o idénticamente distribuidas (i.i.d.). Para cualquier variable aleatoria estrictamente estacionaria: .. math:: (x_t,x_{t+k})\sim i.i.d(\mu,\sigma^2) .. math:: (x_{t+\tau},x_{t+k+\tau})\sim i.i.d(\mu,\sigma^2) Prueba de Estacionariedad ~~~~~~~~~~~~~~~~~~~~~~~~~ La prueba de Dickey-Fuller (David Dickey y Wayne Fuller) permite identificar si un conjunto de datos provienen de un proceso estacionario. También se conoce como prueba D-F. **Hipótesis:** :math:`H_0:` la serie no es estacionaria. :math:`H_1:` la serie es estacionaria. :math:`H_0:` :math:`\varphi_1=1` :math:`H_1:` :math:`\varphi_1<1` :math:`\varphi_1:` Coeficiente de autocorrelación de un retraso. **Coeficiente de autocorrelación:** Es el coeficiente de correlación entre dos valores en una serie temporal. .. math:: \varphi_k=corr(x_t,x_{t-k}) :math:`k:` retraso. Intervalo de tiempo entre los dos perídos. **Coeficiente de correlación de 1 retraso:** :math:`k=1` .. math:: \varphi_1=corr(x_t,x_{t-1}) Es la correlación entre dos valores separados por 1 solo período de tiempo. Prueba de Dickey-Fuller ~~~~~~~~~~~~~~~~~~~~~~~ Se calcula un estadístico de prueba (:math:`\lambda_0`), también se llama estadístico de constrate. Este estadístico de prueba se compara con un valor crítico (:math:`\lambda_{crítico}`). Si :math:`\lambda_0<\lambda_{crítico}:` se rechaza :math:`H_0`. Por tanto, la serie es estacionaria. Otra forma es calculando el :math:`p-valor` con el cual se obtiene la probabilidad de que aceptar la hipótesis nula :math:`H_0`. Si :math:`p-valor` es cercano a cero, la probabilidad de aceptar la hipótesis nula :math:`H_0` es pequeña. :math:`\alpha:` nivel de significancia. :math:`1-\alpha:` nivel de confianza. Si la confianza es del 95% :math:`(1-\alpha=0,95)`, la significancia es del 5% :math:`(\alpha=0,05)` Si :math:`p-valor<\alpha:` se rechaza :math:`H_0`. Por tanto, la serie es estacionaria. .. code:: ipython3 import statsmodels.tsa.stattools as sts .. code:: ipython3 sts.adfuller(datos.Precio) .. parsed-literal:: (-5.14735564904873, 1.1249833584986309e-05, 29, 5787, {'1%': -3.4314804999155433, '5%': -2.8620395736712436, '10%': -2.5670359210987224}, 53341.43530925218) ``(-5.147355649048741,`` ← :math:`\lambda_0` ``1.1249833584985765e-05,`` ← :math:`p-valor` ``29,`` ← Período de tiempo con el que existe autocorrelación. ``5787,`` ← Cantidad de datos de la serie de tiempo. :math:`\lambda_0=-5,147355649048741` **Valores críticos :math:`(\lambda_{crítico})` dependiendo del nivel de confianza:** ``{'1%': -3.4314804999155433, '5%': -2.8620395736712436, '10%': -2.5670359210987224},`` Para un nivel de confianza del 95%, la serie de tiempo es estacionaria: .. math:: \lambda_0=-5,147355649048741<\lambda_{crítico}=-2,8620395736712436 La hipótesis nula, :math:`H_0`, se rechaza. **Otra forma:** :math:`p-valor=1,1249833584985765e-05` Para un nivel de confianza del 95%, la serie de tiempo es estacionaria: .. math:: p-valor=1,1249833584985765e-05<\alpha=0,05 La hipótesis nula, :math:`H_0`, se rechaza. Sin embargo, el valor de 29 es el número de retrasos utilizado para calcular el estadístico. Esto significa que existe autocorrelación con el período 29 de la serie de tiempo. ``(-5.147355649048741, 1.1249833584985765e-05, 29,``\ ← Este valor. Lo ideal es tener el este valor menor a 1. .. code:: ipython3 sts.adfuller(wn) .. parsed-literal:: (-76.4332510296946, 0.0, 0, 5816, {'1%': -3.4314748604753023, '5%': -2.862037082045299, '10%': -2.567034594734868}, 73784.13313234002) En este caso no hay autocorrelación: ``(-76.88442938788081, 0.0, 0,``\ ← No hay un período de tiempo en la serie con el que se tenga autocorrelación. Esta serie de tiempo sí es estacionaria. .. code:: ipython3 sts.adfuller(rw) .. parsed-literal:: (-1.5198946901184311, 0.5236477720694186, 0, 7028, {'1%': -3.4312808039348894, '5%': -2.8619513408164483, '10%': -2.566988952715846}, 62547.63026051087) Esta serie de tiempo no es estacionaria a pesar de no presentar autocorrelación. .. math:: \lambda_0=-1,5198946901184334>\lambda_{crítico}=-2,8619513408164483 .. math:: p-valor=0,5236477720694175>\alpha=0,05 :math:`H_0` se acepta. Esta conclusión también se llega con los otros niveles de confianza. Estacionalidad (Seasonality) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Se observan tendencias que aparecen de forma cíclica. Ejemplo: las estaciones del clima. Son tendencias repetitivas. Para identificar existencia de estacionalidad la serie de tiempo se puede **descomponer** en lo siguiente: 1. Tendencia: patrón. :math:`\mu` 2. Estacional: ciclos. :math:`S` 3. Residual: error. :math:`\epsilon` **Descomposición clásica:** Se espera relación lineal entre las tres partes de la serie de tiempo. Puede ser una descomposición **aditiva** o **multiplicativa**. **1. Aditiva:** .. math:: X_t=\mu_t+S_t+\epsilon_t **2. Multiplicativa:** .. math:: X_t=\mu_t \times S_t \times \epsilon_t .. code:: ipython3 from statsmodels.tsa.seasonal import seasonal_decompose **Aditiva:** .. code:: ipython3 s_dec_additive = seasonal_decompose(rw, model = "additive") s_dec_additive.plot() plt.show() .. image:: output_92_0.png El primer gráfico es la serie de tiempo origial, sin descomponer. El segundo gráfico es la tendencia, si es similar al primero, la serie de tiempo no es estacional. Si el gráfico de la estacionalidad, tercer gráfico, se parece a un rectángulo, es porque los valores están oscilando de un lado a otro y el gráfico es muy pequeño para identificar esos cambios. Esto significa que, para cada período no existe un patrón cíclico completo. Con esto se sugiere que no hay estacionalidad. **Multiplicativa:** .. code:: ipython3 s_dec_multiplicative = seasonal_decompose(rw, model = "multiplicative") s_dec_multiplicative.plot() plt.show() .. image:: output_95_0.png Misma conclusión, no hay estacionalidad. Autocorrelación ~~~~~~~~~~~~~~~ .. math:: corr(x_t,x_{t-k}) **Función de autocorrelación - ACF (Autocorrelation Funtion):** Calcula la autocorrelación para cualquier retraso :math:`(k)`. ACF ~~~ .. code:: ipython3 import statsmodels.graphics.tsaplots as sgt .. code:: ipython3 sgt.plot_acf(datos.Precio, lags = 40, zero = False) plt.title("ACF", size = 24) plt.show() .. image:: output_102_0.png ``lags = 40``: retrasos. En este caso, los 40 períodos antes del período actual. ``zero = False``: para no incluir el período actual. No es necesario mostrar la autocorrelación entre cada valor y sí mismo poque es 1. El área sombreada en el gráfico representa la signifación de los valores de la autocorrelación indicando si son significativamente distintos de cero. Como cada valor de autocorrelación está por encima del área sombreada, esto indica que los coeficientes de autocorrelación son significativos. **Conclusión: la serie de tiempo está autocorrelacionada.** .. code:: ipython3 sgt.plot_acf(wn, lags = 40, zero = False) plt.title("ACF del Ruido Blanco", size = 24) plt.show() .. image:: output_104_0.png La mayoría de los coeficientes de autocorrelación no son significativos porque están dentro del área sombreada. Esto indica que no hay autocorrelación para ningún retraso. Esto es uno de los supuestos del Ruido Blanco. **Conclusión: la serie de tiempo no está autocorrelacionada.** .. code:: ipython3 sgt.plot_acf(rw, lags = 40, zero = False) plt.title("ACF de la Caminata Aleatoria", size = 24) plt.show() .. image:: output_106_0.png **Función de autocorrelación parcial - PACF (Partial Autocorrelation Funtion):** Se determina el efecto que tiene el valor del período :math:`t-k` sobre el período :math:`t`. No determina los efectos entre los períodos intermedios. **Conclusión: la serie de tiempo está autocorrelacionada.** PACF ~~~~ .. code:: ipython3 sgt.plot_pacf(datos.Precio, lags = 40, zero = False, method = ('ols')) plt.title("PACF", size = 24) plt.show() .. image:: output_110_0.png ``method = ('ols')``: método para determinar el PACF. Método de mínimos cuadrados ordinarios (OLS-Ordinary Least Squares). **Conclusión: la serie de tiempo está autocorrelacionada.** .. code:: ipython3 sgt.plot_pacf(wn, lags = 40, zero = False, method = ('ols')) plt.title("PACF para Ruido Blanco", size = 24) plt.show() .. image:: output_113_0.png **Conclusión: la serie de tiempo no está autocorrelacionada.** .. code:: ipython3 sgt.plot_pacf(rw, lags = 40, zero = False, method = ('ols')) plt.title("PACF para la Caminata Aleatoria", size = 24) plt.show() .. image:: output_115_0.png **Conclusión: la serie de tiempo no está autocorrelacionada.**